//
//  OMTDiskCache.m
//  Pods
//
//  Created by yizhaorong on 08/06/2017.
//
//

#import "OMTDiskCache.h"
#import "YYDiskCache.h"
#import "MJExtension.h"
#import <OMTCoreKit/NSFileManager+Extension.h>

// 数组
static NSString *const kArray = @"NSArray";
// 字典
static NSString *const kDictionary = @"NSDictionary";
// 字符串
static NSString *const kString = @"NSString";
// NSData
static NSString *const kData = @"NSData";


@interface OMTDiskCache ()

@property (nonatomic, strong) YYDiskCache *diskCache;

@property (nonatomic, strong) YYDiskCache *typeCache;

@end

@implementation OMTDiskCache

+ (instancetype)sharedInstance {
    static OMTDiskCache *instance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [OMTDiskCache new];
    });
    return instance;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        NSString *path = [[NSFileManager defaultManager].omt_libCachePath stringByAppendingPathComponent:@"onemt.sdk.cache"];
        _diskCache = [[YYDiskCache alloc] initWithPath:path];
        
        NSString *typePath = [[NSFileManager defaultManager].omt_libCachePath stringByAppendingPathComponent:@"onemt.sdk.cache.type"];
        _typeCache = [[YYDiskCache alloc] initWithPath:typePath];
    }
    return self;
}

+ (void)setObject:(id)object key:(NSString *)key {
    OMTDiskCache *cache = [OMTDiskCache sharedInstance];
    NSString *type = [self typeFromObject:object];
    [self setType:type key:key];
    if ([type hasPrefix:kArray] && type.length > kArray.length) {
        type = [type stringByReplacingOccurrencesOfString:[kArray stringByAppendingString:@"_"] withString:@""];
        Class class = NSClassFromString(type);
        [cache.diskCache setObject:[[class mj_keyValuesArrayWithObjectArray:object] mj_JSONString] forKey:key];
        return;
    }
    [cache.diskCache setObject:[object mj_JSONString] forKey:key];
}

+ (id)objectForKey:(NSString *)key {
    OMTDiskCache *cache = [OMTDiskCache sharedInstance];
    NSString *type = [self typeForKey:key];
    NSString *json = (NSString *)[cache.diskCache objectForKey:key];
    if (!json) return nil;
    if ([type hasPrefix:kArray] && type.length > kArray.length) {
        type = [type stringByReplacingOccurrencesOfString:[kArray stringByAppendingString:@"_"] withString:@""];
        Class class = NSClassFromString(type);
        return [class mj_objectArrayWithKeyValuesArray:json];
    } else if ([type isEqualToString:kDictionary]) {
        return [NSJSONSerialization JSONObjectWithData:[json dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableLeaves error:nil];
    } else if ([type isEqualToString:kData]) {
        return [json dataUsingEncoding:NSUTF8StringEncoding];
    } else if ([type isEqualToString:kArray]) {
        return [NSMutableArray mj_objectArrayWithKeyValuesArray:json];
    } else if ([type isEqualToString:kString]) {
        return json;
    } else {
        Class class = NSClassFromString(type);
        return [class mj_objectWithKeyValues:json];
    }
}

+ (void)clearCache {
    OMTDiskCache *cache = [OMTDiskCache sharedInstance];
    [cache.diskCache removeAllObjects];
    [cache.typeCache removeAllObjects];
}

#pragma mark - Private
+ (void)setType:(NSString *)type key:(NSString *)key {
    OMTDiskCache *cache = [OMTDiskCache sharedInstance];
    [cache.typeCache setObject:type forKey:key];
}

+ (id)typeForKey:(NSString *)key {
    OMTDiskCache *cache = [OMTDiskCache sharedInstance];
    return [cache.typeCache objectForKey:key];
}

+ (NSString *)typeFromObject:(id)object {
    if ([object isKindOfClass:[NSArray class]]) {
        id firstObject = [object firstObject];
        if ([firstObject isKindOfClass:[NSString class]]) {
            return kArray;
        } else {
            return [NSString stringWithFormat:@"%@_%@", kArray, [self typeFromObject:firstObject]];
        }
    } else if ([object isKindOfClass:[NSDictionary class]]) {
        return kDictionary;
    } else if ([object isKindOfClass:[NSString class]]) {
        return kString;
    } else if ([object isKindOfClass:[NSData class]]) {
        return kData;
    } else {
        return NSStringFromClass([object class]);
    }
}

@end
